using System;
using System.Collections.Generic;
using System.Text;

namespace NCommet.Core.Agents
{
    /// <summary>
    /// ISearcher is an interface declaring a text search engine. The interface provides methods to update
    /// the search index and methods to perform search queries.
    /// </summary>
    public interface ISearcher
    {
        /// <summary>
        /// Deletes the indexed content for the given item id.
        /// </summary>
        /// <param name="ItemId">The given item id.</param>
        void DeleteContent(int ItemId);

        /// <summary>
        /// Inserts content for the given item id into the index. The content is
        /// divided into logical categories (or fields). Each category matches a numeric value
        /// defined by the application.
        /// </summary>
        /// <param name="ItemId">The given item id.</param>
        /// <param name="Content">A dictionary of field/content value.</param>
        void InsertContent(int ItemId, IDictionary<int, string> Content);

        /// <summary>
        /// Updates the indexed content for the given item id. The content is divided into logical
        /// categories (or fields). Each category matches a numeric value defined by the application.
        /// </summary>
        /// <param name="ItemId">The given item id.</param>
        /// <param name="Content">A dictionary of field/content value.</param>
        void UpdateContent(int ItemId, IDictionary<int, string> Content);

        /// <summary>
        /// Searches the index for the given text. The text is only searched in the designated categories.
        /// </summary>
        /// <param name="TextToFind">The given text.</param>
        /// <param name="Categories">The given categories.</param>
        /// <param name="OnlyResultsWithAllWords">If true, it will only return results containing all words in the query.</param>
        /// <returns>A list of <see cref="ISearchResult"/> objects that contain the id of the item that matches
        /// the search and a list of the categories where the text query was located.</returns>
        IList<ISearchResult> FindText(string TextToFind, List<int> Categories, bool OnlyResultsWithAllWords);

        /// <summary>
        /// Spots the exact area inside the string TextToSpot where TextToFind made a match.
        /// This method is useful when the implementation does not require TextToSpot to be equal to
        /// TextToFind, e.g. when the implementation takes into consideration grammar and linguistic
        /// elements, providing more intelligent results.
        /// </summary>
        /// <param name="TextToFind">The text to find.</param>
        /// <param name="TextToSpot">The text to spot.</param>
        /// <returns>A list of <see cref="WordOffset"/> objects marking the matching areas.</returns>
        IList<WordOffset> SpotArea(string TextToFind, string TextToSpot);
    }

    /// <summary>
    /// ISearchResult is the interface that holds a search result about a specific item.
    /// </summary>
    public interface ISearchResult
    {
        /// <summary>
        /// The id of the item that was found in the search.
        /// </summary>
        int ItemId
        {
            get;
        }

        /// <summary>
        /// The categories where a match was found for the item.
        /// </summary>
        IList<int> Categories
        {
            get;
        }
    }

    /// <summary>
    /// A structure that is used to mark the boundries of a word inside a string.
    /// It is used from the searcher to mark the exact word that matched a search result
    /// and it is particular useful when the searcher matches not only the requested word
    /// but its grammatical variations as well.
    /// </summary>
    public struct WordOffset
    {
        /// <summary>
        /// The index where the word ends.
        /// </summary>
        public int WordEnd;

        /// <summary>
        /// The index where the word starts.
        /// </summary>
        public int WordStart;

        /// <summary>
        /// Creates a new <c>WordOffset</c>.
        /// </summary>
        /// <param name="WordStart">The index where the word starts.</param>
        /// <param name="WordEnd">The index where the word ends.</param>
        public WordOffset(int WordStart, int WordEnd)
        {
            this.WordEnd = WordEnd;
            this.WordStart = WordStart;
        }
    }
}
